除了使用內建的驗證方法之外,還可以在序列化器中添加自定義的 validate_<field_name>
方法來處理其他的驗證邏輯。
from rest_framework import serializers
from my_app.models import UserProfile
class UserProfileSerializer(serializers.ModelSerializer):
class Meta:
model = UserProfile
fields = ['id', 'username', 'is_authenticated', 'age']
# fields = '__all__'
def validate_age(self, value):
if value < 18:
raise serializers.ValidationError("Age must be at least 18.")
return value
from my_app.serializers import UserProfileSerializer
# 假設我們有一個新用戶的數據
user_data = {
'username': 'Curry',
'email': 'curry@example.com',
'age': 16
}
# 初始化序列化器,並傳入數據
serializer = UserProfileSerializer(data=user_data)
# 檢查數據是否有效
if serializer.is_valid():
# 如果有效,保存數據
user_profile = serializer.save()
print("User profile created:", user_profile)
else:
# 如果無效,打印錯誤
print("Validation errors:", serializer.errors)
# Validation errors: {'age': ['Age must be at least 18.']}
如果 models 之間有關聯像是外建字段或是多對多的關聯,我們可以使用嵌套序列化來處理這些關聯數據來處理關聯數據。
class Order(models.Model):
order_number = models.CharField(max_length=20)
order_date = models.DateField(auto_now=True)
user_profile = models.ForeignKey(UserProfile, related_name='orders', on_delete=models.CASCADE)
def __str__(self):
return self.order_number
related_name='orders'
來設定反向關聯的名稱,這樣我們就可以使用 orders 來訪問與 UserProfile 關聯的所有 Order 實例class OrderSerializer(serializers.ModelSerializer):
class Meta:
model = Order
fields = ['order_number', 'order_date']
class UserProfileSerializer(serializers.ModelSerializer):
orders = OrderSerializer(many=True, read_only=True)
order_id_list = serializers.ListField(write_only=True, child=serializers.IntegerField(), required=False)
class Meta:
model = UserProfile
fields = ['username', 'is_authenticated', 'age', 'message', 'orders']
我們能夠根據經過驗證的資料傳回完整的物件實例這件事在 serializer 裡面進行,我們可以去實作.create()和.update()方法或是只實作其中一個方法,因應自己的需求而定。
延續著上面的 UserProfileSerializer 範例來實作兩個方法
class UserProfileSerializer(serializers.ModelSerializer):
orders = OrderSerializer(many=True, read_only=True)
order_id_list = serializers.ListField(write_only=True, child=serializers.IntegerField(), required=False)
class Meta:
model = UserProfile
fields = ['username', 'is_authenticated', 'age', 'message', 'orders']
def create(self, validated_data):
order_id_list = validated_data.pop('order_id_list', None)
user_profile = UserProfile.objects.create(**validated_data)
if order_id_list is not None:
for order_id in order_id_list:
user_profile.orders.add(Order.objects.get(id=order_id))
return user_profile
def update(self, instance, validated_data):
order_id_list = validated_data.pop('order_id_list', None)
if order_id_list is not None:
instance.orders.clear()
for order_id in order_id_list:
instance.orders.add(Order.objects.get(id=order_id))
for attr, value in validated_data.items():
setattr(instance, attr, value)
instance.save()
return instance
from my_app.serializers import UserProfileSerializer, OrderSerializer
# 先建立兩個 Order 實例
order1 = Order.objects.create(order_number='0001', order_date='2022-01-01')
order2 = Order.objects.create(order_number='0002', order_date='2022-01-02')
# 建立一個新用戶的數據
user_data = {
'username': 'Curry',
'age': 18,
'message': 'This is Curry profile.',
'order_id_list': [order1.id, order2.id]
}
# 初始化序列化器,並傳入數據
serializer = UserProfileSerializer(data=user_data)
# 檢查數據是否有效
if serializer.is_valid():
# 如果有效,保存數據
user_profile = serializer.save()
print("User profile created:", user_profile)
else:
print("Validation errors:", serializer.errors)
這樣我們就可以根據用戶提交的數據來創建或更新 UserProfile 實例,並處理與 UserProfile 關聯的 Order 實例
今天我們學習了如何在序列化器中添加自定義的字段驗證方法,以及如何使用嵌套序列化來處理模型之間的關聯數據。下一篇文章我們將會學習如何使用信號(Signals)。